package com.kuang.unsafe;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * List 单线程下是安全的，并发情况下不安全。
 * 并发情况下，有些集合类会报错：并发修改异常  ConcurrentModificationException
 */
public class ListTest {
    public static void main(String[] args) {
        /**
         * 并发下ArrayList不安全
         *
         * 解决方案：
         * 1. Vector                                List<String> list = new Vector<>();
         * 2. Collections.synchronizedList          List<String> list = Collections.synchronizedList(new ArrayList<>());
         * 3. CopyOnWriteArrayList()                List<String> list = new CopyOnWriteArrayList<>();
         *      写入时复制，cow，计算机程序设计领域的一种优化策略
         *      多个线程调用的时候，list, 读取的时候，固定的，写入（覆盖）
         *      在写入的时候避免重复，造成数据问题！
         *      读写分类
         *      CopyOnWriteArrayList比 Vector 好在哪里？  vector 用的 sychronized，效率低一点，CopyOnWriteArrayList比 用了lock锁，效率搞一点
         *
         */
        // 单线程没有问题
        //List<String> list = new ArrayList<>();
        //for (int i = 0; i < 1000; i++) {
        //    list.add(UUID.randomUUID().toString().substring(0,5));
        //    System.out.println(list);
        //}

        //出现并发修改异常
        //List<String> list = new ArrayList<>();
        //for (int i = 0; i < 1000; i++) {
        //    new Thread(()->{
        //        list.add(UUID.randomUUID().toString().substring(0,5));
        //        System.out.println(list);
        //    }).start();
        //}

        // 方式1 Vector
        //List<String> list = new Vector<>();
        //for (int i = 0; i < 1000; i++) {
        //    new Thread(()->{
        //        list.add(UUID.randomUUID().toString().substring(0,5));
        //        System.out.println(list);
        //    }).start();
        //}

        // 方式2 将list抛入Collections.synchronizedList（）
        //List<String> list = Collections.synchronizedList(new ArrayList<>());
        //for (int i = 1; i <= 10; i++) {
        //    new Thread(()->{
        //        list.add(UUID.randomUUID().toString().substring(0,5));
        //        System.out.println(list);
        //    }, String.valueOf(i)).start();
        //}

        // 方式3 new一个写入时复制list, CopyOnWriteArrayList()
        List<String> list = new CopyOnWriteArrayList<>();
        for (int i = 1; i <= 10; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(list);
            }, String.valueOf(i)).start();
        }
    }
}
